/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package es.udc.emarketapp.http.controller.session.shoppingManager;

import es.udc.emarketapp.emarket.model.client.vo.ClientVO;
import es.udc.emarketapp.emarket.model.countryFacade.CountryFacade;
import es.udc.emarketapp.emarket.model.orderDetails.vo.OrderDetailsVO;
import es.udc.emarketapp.emarket.model.orderLine.vo.OrderLineVO;
import es.udc.emarketapp.emarket.model.purchase.purchaseFacade.PurchaseFacade;
import es.udc.emarketapp.emarket.model.purchase.vo.PurchaseVO;
import es.udc.emarketapp.emarket.model.shippingFacade.ShippingFacade;
import es.udc.emarketapp.emarket.model.shoppingFacade.vo.OrderCartVO;
import es.udc.emarketapp.emarket.model.shoppingFacade.vo.OrderLineCartVO;
import es.udc.emarketapp.emarket.model.usersFacade.UsersFacade;
import es.udc.emarketapp.http.controller.session.SessionManager;
import es.udc.fbellas.j2ee.util.exceptions.InternalErrorException;
import es.udc.fbellas.j2ee.util.exceptions.InstanceNotFoundException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

public final class ShoppingManager {

    public final static String SHOPPING_CART_ATTRIBUTE =
            "shoppingCart";
    public final static String SHOPPING_CART_UDS_ATTRIBUTE =
            "shoppingCartUds";
    public final static String VALUE_SHOPPING_CART_ATTRIBUTE =
            "valueShoppingCart";
    public final static String SENDPRICE_SHOPPING_CART_ATTRIBUTE =
            "sendPriceShoppingCart";
    public final static String TOTAL_SHOPPING_CART_ATTRIBUTE =
            "totalShoppingCart";
    public final static String PAYMENT_FORM =
            "paymentForm";
    public final static String ID_USER_SESSION_ATTRIBUTE = "idUser";
    //uns shopping cart es una lista de OrdersVO que se guarda en la sesion
    //private List<OrderVO> orders;

    private ShoppingManager() {
    }

    public final static void addOrder(OrderCartVO order, HttpServletRequest request) {
        HttpSession session = request.getSession(true);
        List<OrderCartVO> orders = (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);
        if (orders == null) {
            orders = new ArrayList<OrderCartVO>();
        }
        orders.add(order);

        session.setAttribute(SHOPPING_CART_ATTRIBUTE, orders);

    }

    public final static List<OrderCartVO> getOrders(HttpServletRequest request) {

        HttpSession session = request.getSession(false);

        return (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);

    }

    //Devuelve el pedido para ese vendedor
    public final static OrderCartVO getOrder(String idVendedor, HttpServletRequest request) {

        HttpSession session = request.getSession(false);
        List<OrderCartVO> orders = (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);

        OrderCartVO sellerOrder = null;

        if (orders != null) {

            for (OrderCartVO order : orders) {
                if (((order.getOrderDetails()).getIdVendedor()).equals(idVendedor)) {
                    sellerOrder = order;
                }
            }
        }

        return sellerOrder;
    }

    public final static void deleteOdrer(String idVendedor, HttpServletRequest request) {

        HttpSession session = request.getSession(false);
        List<OrderCartVO> orders = (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);

        OrderCartVO sellerOrder = null;

        for (OrderCartVO order : orders) {
            if (((order.getOrderDetails()).getIdVendedor()).equals(idVendedor)) {
                sellerOrder = order;
            }
        }

        orders.remove(sellerOrder);
        calculateTotalOrdersPrices(session);

        session.setAttribute(SHOPPING_CART_ATTRIBUTE, orders);
    }

    public final static void addOrderLine(String idVendedor,
            OrderLineCartVO orderLine, HttpServletRequest request) {

        HttpSession session = request.getSession(false);
        List<OrderCartVO> orders = (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);

        OrderCartVO sellerOrder = null;
        Long uds = new Long(0);

        for (OrderCartVO order : orders) {
            if (((order.getOrderDetails()).getIdVendedor()).equals(idVendedor)) {
                sellerOrder = order;
            }
        }

        //miramos si ya existe una linea de pedido para ese producto
        OrderLineCartVO orderLineSaved = null;
        for (OrderLineCartVO oLine : sellerOrder.getOrderLines()) {
            if ((oLine.getIdProd()).equals(orderLine.getIdProd())) {
                orderLineSaved = oLine;
            }
        }

        //si existe una linea para ese producto
        if (orderLineSaved != null) {

            uds = orderLine.getUds();
            Long newQuantity = orderLine.getUds() + orderLineSaved.getUds();
            orderLine.setUds(newQuantity);
            System.out.println("nueva catnidad = " + orderLine.getUds());

            orders.remove(sellerOrder);

            sellerOrder.removeOrderLine(orderLineSaved);
            //se mete la misma orden de linea con la nueva cantidad
            sellerOrder.addOrderLine(orderLine);

        } else {//if (orderLineSaved != null)

            orders.remove(sellerOrder);
            sellerOrder.addOrderLine(orderLine);
            uds = orderLine.getUds();
        }

        sellerOrder = updateOrderPrices(sellerOrder, request);

        orders.add(sellerOrder);

        calculateTotalOrdersPrices(session);

        session.setAttribute(SHOPPING_CART_ATTRIBUTE, orders);

        Long cartUds = (Long) session.getAttribute(SHOPPING_CART_UDS_ATTRIBUTE);
        if (cartUds == null) {
            cartUds = new Long(0);
        }
        session.setAttribute(SHOPPING_CART_UDS_ATTRIBUTE, cartUds + uds);

    }

    public final static void deleteOrderLine(String idVendedor,
            Long nLine, HttpServletRequest request) {

        HttpSession session = request.getSession(false);
        List<OrderCartVO> orders = (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);

        OrderCartVO sellerOrder = null;
        Long uds = new Long(0); //unidades que dejaran de estar en el carro

        for (OrderCartVO order : orders) {
            if (((order.getOrderDetails()).getIdVendedor()).equals(idVendedor)) {
                sellerOrder = order;
            }
        }

        //recuperamos las lineas de la orden
        if (sellerOrder != null) {

            if ((sellerOrder.getOrderLines()).size() == 1) {
                uds = ((OrderLineCartVO) ((sellerOrder.getOrderLines().toArray())[0])).getUds();
                deleteOdrer(idVendedor, request);

            } else {

                OrderLineCartVO orderLine = null;
                for (OrderLineCartVO oLine : sellerOrder.getOrderLines()) {
                    if ((oLine.getnLinea()).equals(nLine)) {
                        orderLine = oLine;
                    }
                }

                if (orderLine != null) {

                    uds = orderLine.getUds();

                    orders.remove(sellerOrder);

                    sellerOrder.removeOrderLine(orderLine);


                    sellerOrder = updateOrderPrices(sellerOrder, request);

                    orders.add(sellerOrder);

                    calculateTotalOrdersPrices(session);

                    session.setAttribute(SHOPPING_CART_ATTRIBUTE, orders);
                }// if(orderLine != null)
            }//if if((sellerOrder.getOrderLines()).size() == 1)
        }// if (sellerOrder != null)


        Long cartUds = (Long) session.getAttribute(SHOPPING_CART_UDS_ATTRIBUTE);

        session.setAttribute(SHOPPING_CART_UDS_ATTRIBUTE, cartUds - uds);


    }

    public static void registerBuy(HttpServletRequest request)
            throws InternalErrorException, InstanceNotFoundException {

        HttpSession session = request.getSession(false);
        List<OrderCartVO> orders = (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);

        PurchaseFacade purchaseFacade = new PurchaseFacade();

        //se crea la compra sin valor, la fecha actual se
        //registra en el dao

        String idClient = SessionManager.getIdUser(request);

        PurchaseVO purchase = new PurchaseVO(idClient, null, 0, PAYMENT_FORM);

        PurchaseVO purchaseSaved =
                purchaseFacade.createPurchase(purchase);

        double total = 0;

        for (OrderCartVO order : orders) {

            OrderDetailsVO orderDetails = order.getOrderDetails();

            total = total + orderDetails.getValor() + orderDetails.getGastosEnvio();

            orderDetails.setnCompra(purchaseSaved.getnCompra());

            OrderDetailsVO orderSaved = purchaseFacade.createOrder(orderDetails);

            Collection<OrderLineCartVO> orderLines = order.getOrderLines();

            /*
            suponemos que en OrderDetails el peso,
            gastos envio y precio
            del pedido ya esta calculado
             */

            /*se calcula el valor de la compra, sumando
            el valor y gastos de envio de cada pedido*/


            for (OrderLineCartVO orderLine : orderLines) {

                OrderLineVO orderLineVO = new OrderLineVO(orderLine.getnLinea(),
                        orderSaved.getnPedido(), purchaseSaved.getnCompra(),
                        orderLine.getIdProd(), orderLine.getUds(),
                        orderLine.getValor(), orderLine.getPeso());

                purchaseFacade.createOrderLine(orderLineVO);
            }

        }

        purchaseFacade.updatePurchaseValue(purchaseSaved.getnCompra(), total);

    }

    public static OrderCartVO updateOrderPrices(OrderCartVO order,
            HttpServletRequest request) {
        /* Actualiza el peso y valor de una orden, segun los items y actualiza el
         * precio de envio
         */


        Collection<OrderLineCartVO> orderLines = order.getOrderLines();

        double weight = 0;
        double price = 0;

        for (OrderLineVO oLine : orderLines) {
            weight = weight + oLine.getPeso();
            price = price + oLine.getValor();
        }

        OrderDetailsVO orderDetails = order.getOrderDetails();
        orderDetails.setPeso(weight);
        orderDetails.setValor(price);


        /*********************/
        /*
        si idclient no autenticado el pais de envio sera el del defaultlocale
        sino se mira el pais del cliente y sa recupera el gasto de envio
         */
        String idCountry = null;
        double gastosEnvio = 0;

        ActionMessages errors = new ActionMessages();

        String idClient = SessionManager.getIdUser(request);

        if (!SessionManager.isUserAuthenticated(request)) {
            idCountry = Locale.getDefault().getCountry();

        } else {

            try {
                UsersFacade usersFacade = new UsersFacade();
                ClientVO client = usersFacade.findClientById(idClient);

                CountryFacade countryFacade = new CountryFacade();
                idCountry = countryFacade.findIdByName(client.getPaisEnvio());

            } catch (Exception e) {
                System.out.println(e.getMessage());
                errors.add("InternalError",
                        new ActionMessage("ErrorMessages.shoppingManager.internalError"));
            }

        }

        try {
            ShippingFacade shippingFacade = new ShippingFacade();

            gastosEnvio = shippingFacade.calculateShippingCosts(
                    orderDetails.getIdVendedor(), idCountry, weight);
        } catch (InternalErrorException e) {
            System.out.println(e.getMessage());
            errors.add("InternalError",
                    new ActionMessage("ErrorMessages.shoppingManager.internalError"));
        }


        orderDetails.setGastosEnvio(gastosEnvio);

        order.setOrderDetails(orderDetails);

        return order;
        /*
         * se recorre  OrderCartVO.getOrderLines
         * se suman los precios de los pedidos
         * precio = precio + o.getPrecio();
         *
         * se calculan los gastos envio
         * Double gastosEnvio = calcupateSendPrice(OrderCartVO);
         *
         * se actualizan gastos de envio y valor del pedido
         * OrderCartVO.setGastosEnvio(gastosEnvio);
         * OrderCartVO.setValor(precio + gastosEnvio);
         *
         **/
    }

    public static void calculateTotalOrdersPrices(HttpSession session) {

        List<OrderCartVO> orders = (List<OrderCartVO>) session.getAttribute(SHOPPING_CART_ATTRIBUTE);

        double valor = 0;
        double gastosEnvio = 0;

        for (OrderCartVO order : orders) {
            valor = valor + order.getOrderDetails().getValor();
            gastosEnvio = gastosEnvio + order.getOrderDetails().getGastosEnvio();
            System.out.println("sumando" + order.getOrderDetails().getValor());
        }
        System.out.println("valor total = " + valor);

        /*
        int num = (int) (gastosEnvio * 100);
        double gEnvio = num / 100.0;
        */
        double gEnvio = gastosEnvio;
        /*
        double total = valor + gastosEnvio;
        num = (int) (total * 100);
        total = num / 100.0;
        */
        double total = valor + gastosEnvio;
        /*
        num = (int) (valor * 100);
        valor = num / 100.0;
         */
        

        session.setAttribute(VALUE_SHOPPING_CART_ATTRIBUTE, valor);
        session.setAttribute(SENDPRICE_SHOPPING_CART_ATTRIBUTE, gEnvio);
        session.setAttribute(TOTAL_SHOPPING_CART_ATTRIBUTE, total);

    }

    public static void emptyCart(HttpServletRequest request) {

        HttpSession session = request.getSession(true);
        session.setAttribute(SHOPPING_CART_ATTRIBUTE, null);
        session.setAttribute(VALUE_SHOPPING_CART_ATTRIBUTE, null);
        session.setAttribute(SENDPRICE_SHOPPING_CART_ATTRIBUTE, null);
        session.setAttribute(TOTAL_SHOPPING_CART_ATTRIBUTE, null);
        session.setAttribute(SHOPPING_CART_UDS_ATTRIBUTE, null);

    }
}
